/*
    Code : Dzlua
    Email: 505544956@qq.com
    Time : 2017/05/28
*/
#ifndef _DZLUA_FILE_H_
#define _DZLUA_FILE_H_
#pragma once

#include "../export.h"

#include <string>
#include <memory>

namespace dzlua {

class DZLUA_EXPORT FilePath {
public:
    typedef unsigned long long uintmax;
    #define DZ_FILEPATH_SIZE_ERROR ((uintmax)-1)
public:
    //new FilePath
    static std::unique_ptr<FilePath> NewFilePath(FilePath* path);
    static std::unique_ptr<FilePath> NewFilePath(const std::string& path = std::string());
    static std::unique_ptr<FilePath> NewFilePath(const std::wstring& path);
    // system temp path
    static std::unique_ptr<FilePath> TempPath();
    //Get current work path
    static std::unique_ptr<FilePath> CurrentPath();
    //Get exe path
    static std::unique_ptr<FilePath> MoudlePath();
    /*
        base == nullptr -> base == CurrentPath();
        The function returns the absolute pathname corresponding to pval relative to the pathname base:
        1.If pval.has_root_name() && pval.has_root_directory() the function returns pval.
        2.If pval.has_root_name() && !pval.has_root_directory() the function returns 
            pval.root_name() / absolute(base).root_directory() / absolute(base).relative_path() / pval.relative_path().
        3.If !pval.has_root_name() && pval.has_root_directory() the function returns absolute(base).root_name() / pval.
        4.If !pval.has_root_name() && !pval.has_root_directory() the function returns absolute(base) / pval.

        ('c\\d\\e\\f.g','a:\\b\\')->"a:\\b\\c\\d\\e\\f.g";
    */
    static std::unique_ptr<FilePath> AbsolutePath(FilePath* pval, FilePath* base = nullptr);

    /*
        current_path:'E:\\a\\b\\c'
        ('c\\d\\e\\f.g')->"E:\\a\\b\\c\\c\\d\\e\\f.g";

        is equal to AbsolutePath('aaa', nullptr) ?
    */
    static std::unique_ptr<FilePath> SystemComplete(FilePath* path);

    /*
        read the file to string.
        std::string file = "testfile.txt";
        std::string con = File::ReadFile(file);
    */
    static std::string ReadFile(const std::string& input);
    static std::wstring ReadFile(const std::wstring& input);
    /*
        write the string to file.
        std::string file = "testfile.txt";
        std::string con = "this is the text content, used for test dzlua::File.";
        bool bok = File::WriteFile(file, con);
    */
    static bool WriteFile(const std::string& input, const std::string& con);
    static bool WriteFile(const std::wstring& input, const std::wstring& con);

    /* if file not exist, return empty.*/
    static std::string GetShortPath(const std::string& file);
    static std::wstring GetShortPath(const std::wstring& file);

public:
    virtual void append(FilePath* path) = 0;
    virtual void append(const std::string& path) = 0;
    virtual void append(const std::wstring& path) = 0;

    virtual void clear() = 0;
    virtual bool empty() = 0;
    
    virtual std::string string() const = 0;
    virtual std::wstring wstring() const = 0;
    virtual std::string u8string() const = 0;

    virtual std::unique_ptr<FilePath> root_name() const = 0;
    virtual std::unique_ptr<FilePath> root_path() const = 0;
    virtual std::unique_ptr<FilePath> root_dir() const = 0;
    virtual std::unique_ptr<FilePath> relative() const = 0;
    virtual std::unique_ptr<FilePath> parent() const = 0;
    virtual std::unique_ptr<FilePath> filename() const = 0;
    virtual std::unique_ptr<FilePath> stem() const = 0;
    virtual std::unique_ptr<FilePath> extension() const = 0;
    virtual std::unique_ptr<FilePath> dir() const = 0;

    virtual bool has_root_path() const = 0;
    virtual bool has_root_name() const = 0;
    virtual bool has_root_dir() const = 0;
    virtual bool has_relative() const = 0;
    virtual bool has_parent() const = 0;
    virtual bool has_filename() const = 0;
    virtual bool has_stem() const = 0;
    virtual bool has_extension() const = 0;
    virtual bool is_absolute() const = 0;
    virtual bool is_relative() const = 0;

    virtual bool is_exist() const = 0;
    virtual bool is_directory() const = 0;
    virtual bool is_file() const = 0;

    virtual void remove_filename() = 0;
    virtual void replace_filename(FilePath* filename) = 0;
    virtual void replace_extension(FilePath* extension) = 0;

    virtual uintmax file_size() = 0;
    //virtual bool create_dir() = 0;
};

} // end namespace dzlua

#endif //_DZLUA_FILE_H_